全球資訊網路(World Wide Web, WWW)最早用於學術研究機構,用於分享研究報告成果。起初常見型態為:資訊分享者自行建立Web伺服器,提供HTML靜態頁面,讓資訊受者透過瀏覽器取得資訊。
英國科學家提姆·柏內茲-李於1989年發明了全球資訊網。1990年他在瑞士CERN的工作期間編寫了第一個網頁瀏覽器。網頁瀏覽器於1991年1月向其他研究機構發行,並於同年8月向公眾開放。^1
「資訊分享者自行建立Web伺服器,提供HTML靜態頁面,讓資訊受者透過瀏覽器取得資訊」這從現在來看,可能分成兩個不同維度的類型:
隨後出現部落格平台、線上論壇,出現可以提供資訊內容的網站使用者。在此,網站內容不再簡單以HTMl方式儲存,更多的內容儲存於資料庫,由使用者提供,動態的提供給瀏覽器。這是 動態網頁 和 Web 2.0 。
此外伴隨者瀏覽器腳本語言與API的逐漸統一,確立了 ECMAScript / JavaScript 在瀏覽器的地位,結束了過往百家爭鳴的情況(不過現在還有一些原生支援特殊腳本語言的瀏覽器存在,但JavaScript已成主流)。
似動非動,吸引人眼球由JS、CSS建立動畫效果的網頁內容開始玲瑯滿目地出現。
1996年11月,網景正式向ECMA(歐洲電腦製造商協會)提交語言標準。1997年6月,ECMA以JavaScript語言為基礎制定了ECMAScript標準規範ECMA-262。JavaScript成為了ECMAScript最著名的實現之一。除此之外,ActionScript和JScript也都是ECMAScript規範的實作語言。^3
其中也還有另一個令人興奮、今天廣泛使用的技術出現: Ajax(Asynchronous JavaScript and XML)。
在現今,Ajax技術主要以XMLHttpRequest
和fetch
兩個API呈現。也可能隱藏在jQuery^4、Axios等比較高層次的套件函式庫之下。
這也使得由瀏覽器處理、在前端渲染生成不同內容的畫面成為可能。儘管這不是當前唯一的技術方式,但有許多別具特色的功能、前後分離的網站都依賴者這項能力。
接著就讓我們來探索幾個取得更新資訊的模式吧!
並非由後端伺服器選染產生HTML畫面的做法^5,主要分有Polling、Long Polling、Websocket還有WebRTC。此外還有比要少見的Server Send Event和multipart/x-mixed-replace
這兩種處理方式。
multipart/x-mixed-replace
本小節除了WebRTC,會探索一下其他的做法。
Polling輪詢。是一種透過Ajax技術不斷去取得新內容的方式。透過Ajax發出的Request和得到的Response遵循著通常的狀態,正常內容會在一定時間內返回,否則視為超時(timeout)。
返回內容依據需求實現。若資源沒有更新,回傳空內容或是舊內容;否則回傳新內容。
實際上超時對於應用整體而言也沒什麼影響,因爲會在下一次取得新的內容。通常而言,在取得內容後也不會立刻再詢問一次新內容。視需要即時更新的情況與內容通常更新的情況,會設置一段間格時間。
由於實現簡單,目前還有不少設計可以見得其身影。
對於一般的Web架構來說,後端架構幾乎無需調整。前端視需要即時更新的情況與內容通常更新的情況,決定何時需要取得新的內容資訊。是由前端,需要呈現資料的一方主動拉取。
內容並非即時。由於是由前端主動詢問拉取的,而且通常而言每次詢問間會有一段間格時間。這段間格時間並不保持雙方連線。因此可能存在資料內容不即時的問題。
此外,由於每次Request可能都是獨立的TCP連線,因此都需要經過TCP的三段式交握連線。這段於網絡消耗而言是而外的看不見的負擔。
這是發生在TCP協議上。HTTP/0.9、HTTP/1.0、HTTP/2.0 都是基於 TCP ,可能發生這個情況。但是 HTTP/3 是基於QUIC,而該是基於UDP下的,可能就沒有影響。
由於Polling非常簡單,因此實驗環境需求也非常簡單。
這裡將透過docker建立一個Nginx服務器。
如果你安裝了Python,也可以透過python -m http.server
執行Python自帶的簡易伺服器。
收先先建立www-data
的資料夾。然後透過docker啓動Nginx:
docker run --name nginx --rm -p 8080:80 -v "${PWD}/www-data":/usr/share/nginx/html nginx
在www-data
資料夾下建立一份content.txt
,並寫入Hello World
的內容。
若資源沒有更新,回傳空內容或是舊內容
對於沒有更新的資源內容,將會回傳就有的內容。因此前端顯式時只需要每次都取代原本顯式內書仍即可。
然後同樣在www-data
資料夾建立index.html
:
<!-- www-data/index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>即時更新內容 - Polling</title>
</head>
<body>
<h1 id="content"></h1>
</body>
<script defer type="module">
const delay = 5000/*ms*/;
const contentEl = document.querySelector('#content');
let timer = null;
async function updateContent(){
let response = await fetch('/content.txt')
contentEl.innerText = await response.text();
timer = setTimeout( updateContent , delay);
}
updateContent();
</script>
</html>
現在,我們可以透過 http://localhost:8080 去瀏覽這個頁面。
這個頁面會每隔5秒去取得一次content.txt
的內容,並顯示在畫面上。所以你可以將content.txt
改成:
Hello Bob!
在5秒內,畫面應該就會更新成新的content.txt
的內容。
本文同時發表於我的隨筆
Server Push / Server Send Event
雖然我這裡把 Server Push 和 Server Send Event 放在一起,但是兩者是完全不同的技術。之後會說道 Server Send Event(SSE) 。至於 Server Push ,實話說我並沒有很了解,能否做到類似的功能對我來說還是未知。只是因爲兩個從命名和行爲模式很像,一開始我也沒有弄得很清楚。